#include <iomanip>
#include <sstream>
#include <utility>

#include "HUD.h"
#include "FontManager.h"
#include "Game.h"
#include "Button.h"
#include "TexturedEntity.h"
#include "FreeTypeFont.h"

#include "GLee.h"
#include <GL/glu.h>

using namespace std;

HUD::HUD(boost::shared_ptr<Game> scene)
    : m_scene(scene), m_pauseBtn(NULL), m_lifesIcon(NULL)
{
}

HUD::~HUD(void)
{
}

bool HUD::initialize(void)
{
    //Viewport[2] stores the width of the viewport, vieport[3] stores the height
    //We pass these into our font so the ortho mode can set the resolution for the window
    GLint viewport[4];
    glGetIntegerv(GL_VIEWPORT, viewport);

    FontManager* fontManager = FontManager::getInstance();
    if (fontManager->hasFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 24)))
    {
        m_font = fontManager->getFont(make_pair("data/textures/ANGRY_BIRDS.ttf", 24));
    }
    else
    {
        m_font = boost::shared_ptr<FreeTypeFont>(new FreeTypeFont("data/textures/ANGRY_BIRDS.ttf",
                              viewport[2], 
                              viewport[3], 
                              24));
        fontManager->addFont(m_font);
    }

    m_pauseBtn = new Button(m_scene);
    m_pauseBtn->setDimension(Dimension(32.0f, 32.0f));
    m_pauseBtn->setPosition(Vector3(20.0f, 20.0f, 0.0f));
    if (!m_pauseBtn->initialize()) {
        std::cerr << "Could not initialize the Button" << std::endl;
        return false;
    }
    m_pauseBtn->setFontSize(18);
    m_pauseBtn->setLabel("II");

    // Initialize the lifes icon in ARCADE mode
    if (m_scene->getGameMode() == ARCADE)
    {
        m_lifesIcon = new TexturedEntity(m_scene, "data/textures/ingamebirds1.tga");
        m_lifesIcon->setPosition(Vector3(896.0f, 578.0f, 0.0f));
        m_lifesIcon->setPixelsSize(Dimension(26.0f, 30.0f));
        m_lifesIcon->setPositionInTexture(Vector3(5.0f, 560.0f, 0.0f));
        m_lifesIcon->setSizeInTexture(Dimension(26.0f, 30.0f));
        m_lifesIcon->initialize();
    }

    //Return success
    return true;
}

void HUD::prepare(float dt)
{
    // Update button
    m_pauseBtn->prepare(dt);
}

void HUD::render(void)
{
    // Render time
    stringstream time;
    Color color = Color(1.0f, 1.0f, 1.0f, 1.0f);
    if (m_scene->getGameMode() == ARCADE)
    {
        time << getElapsedTimeAsString();
    }
    else
    {
        time << getRemainingTimeAsString();
        if (getRemainingSeconds() <= 10)
        {
            color = Color(1.0f, 0.0f, 0.0f, 1.0f);
        }
    }
    m_font->printString(time.str(), 900.0f, 600.0f, color);
    
    // Render remaining lifes in ARCADE mode
    if (m_scene->getGameMode() == ARCADE)
    {
        m_lifesIcon->render();
        stringstream lifesString;
        lifesString << "x " << m_scene->getLifes();
        m_font->printString(lifesString.str(), 914.0f, 565.0f);
    }

    // Render score
    stringstream scoreString;
    scoreString << std::setfill('0') << std::setw(4) << m_scene->getScore();
    m_font->printString(scoreString.str(), 10.0f, 600.0f);

    // Render combo information if applicable
    if (m_scene->getCombo() > 1)
    {
        stringstream comboString;
        comboString << "COMBO x " << m_scene->getCombo();
        m_font->printString(comboString.str(), 10.0f, 530.0f, Color(1.0f, 0.5f, 0.0f, 1.0f));
    }

    // Render button
    m_pauseBtn->render();

}

bool HUD::isPauseButtonPressed(void) const
{
    return m_pauseBtn->isClicked();
}

void HUD::resetPauseButton(void)
{
    m_pauseBtn->setClicked(false);
}

string HUD::getRemainingTimeAsString(void) const
{
    float time = m_scene->getRemainingTime() / 60.0f;
    int minutes = int(time);
    float rem = time - float(minutes);
    int seconds = int(rem * 60.0f);

    stringstream t;
    t << minutes << ":" << std::setfill('0') << std::setw(2) << seconds;
    return t.str();
}

string HUD::getElapsedTimeAsString(void) const
{
    float time = m_scene->getElapsedTime() / 60.0f;
    int minutes = int(time);
    float rem = time - float(minutes);
    int seconds = int(rem * 60.0f);

    stringstream t;
    t << minutes << ":" << std::setfill('0') << std::setw(2) << seconds;
    return t.str();
}

int HUD::getRemainingSeconds(void) const
{
    float time = m_scene->getRemainingTime() / 60.0f;
    int minutes = int(time);
    float rem = time - float(minutes);
    int seconds = int(rem * 60.0f);

    return seconds;
}
